package org.example.filetool.file;

import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.util.*;

/**
 * @Description:
 * @Author: 刘超
 * @Date: 2023-03-30 19:21
 */
public class SftpUtil {

    private static final Logger logger = LoggerFactory.getLogger(SftpUtil.class);

    /**
     * 服务器地址
     */
    private String host;
    /**
     * 服务器端口
     */
    private int port = 22;
    /**
     * sftp用户名
     */
    private String userName;
    /**
     * sftp密码
     */
    private String password;

    private ChannelSftp channelSftp = null;

    private Session session = null;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public SftpUtil() {
    }

    public SftpUtil(String host, int port, String userName, String password) {
        this.host = host;
        this.port = port;
        this.userName = userName;
        this.password = password;
    }

    public void init() {
        //创建JSch对象
        JSch jSch = new JSch();
        try {
            //获取session对象
            session = jSch.getSession(userName, host, port);
            //设置sftp访问密码
            setPassword(password);

            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();
            Channel channel = session.openChannel("sftp");
            channel.connect();
            channelSftp = (ChannelSftp) channel;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void destroy() {
        if (this.channelSftp != null) {
            if (this.channelSftp.isConnected()) {
                this.channelSftp.disconnect();
            }
        }
        if (this.session != null) {
            if (this.session.isConnected()) {
                this.session.disconnect();
            }
        }
    }

    /**
     * 获取SFTP路径下所有文件名，不包含文件夹
     * @param path
     * @return
     * @throws SftpException
     */
    public List<String> getDirFileList(String path) throws SftpException {
        List<String> fileList = new ArrayList<>();
        Vector files = channelSftp.ls(path);
        Iterator iterator = files.iterator();
        while (iterator.hasNext()) {
            ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) iterator.next();
            String filename = entry.getFilename();
            if (".|..".contains(filename)) {//排除根目录，防止一直循环
                String fullPath = path + "/" + filename;
                SftpATTRS attrs = entry.getAttrs();
                if (attrs.isDir()){
                    fileList.addAll(getDirFileList(fullPath));
                } else if (attrs.isReg()) {
                    fileList.add(fullPath);
                }
            }
        }
        return fileList;
    }

    public Map<String, InputStream> getDirFile(String path) throws SftpException {
        Map<String, InputStream> streamMap = new HashMap<>();
        Vector files = channelSftp.ls(path);
        Iterator iterator = files.iterator();
        while (iterator.hasNext()) {
            ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) iterator.next();
            String filename = entry.getFilename();
            if (".|..".contains(filename)) {//排除根目录，防止一直循环
                String fullPath = path + "/" + filename;
                SftpATTRS attrs = entry.getAttrs();
                if (attrs.isDir()){
                    streamMap.putAll(getDirFile(fullPath));
                } else if (attrs.isReg()) {
                    InputStream inputStream = channelSftp.get(fullPath);
                    streamMap.put(fullPath,inputStream);
                }
            }
        }
        return streamMap;
    }
}
